﻿var SPTREESELECOR = "#spExplorerTree";
var previousResultOdataUrl = "";
var currentResultOdataUrl = "";
var nextResultOdataUrl = "";

var requestCache = [];

var currentPageIndex = 1;
var pageNavigationIndexArray = [];

var itemNodeTypeValues = ["SPWeb.Lists.SP.List.Items", "SPWeb.RootWeb.Lists.SP.List.Items"];
var listNodeTypeValues = ["SPWeb.Lists.SP.List", "SPWeb.RootWeb.Lists.SP.List"];

$(document).ready(function () {

    var currentWebUrl = _spPageContextInfo.webAbsoluteUrl;
    $("#txtRootWebUrl").val(currentWebUrl);

    ShowProgress();
    Init();
    LoadURLDropDown();
    LoadJSTree(currentWebUrl);
    SetHeight();
    SetTreeHeight();

    GetAllUsers(currentWebUrl);
    GetAllGroups(currentWebUrl);

    $(window).resize(function () {
        SetHeight();
        SetTreeHeight();
    });
});

function btnGo_Click() {
    var currentWebUrl = $("#txtRootWebUrl").val();
    LoadJSTree(currentWebUrl);
}

function Init() {
    $("#nextResultSet").click(function () {
        NextResultSet();
    });

    $("#previousResultSet").click(function () {
        PreviousResultSet();
    });

    //var isIE = /*@cc_on!@*/false || !!document.documentMode;

    //if (isIE === true) {
    //    $("#btnExportResults").attr('disabled', 'disabled');
    //    $("#btnExportResults").attr("title", "This functionality will not work with IE");
    //    $("#btnExportResults").attr("data-toggle", "tooltip");
    //    $("#btnExportResults").hide();

    //    $("#btnExportProperties").attr('disabled', 'disabled');
    //    $("#btnExportProperties").attr("title", "This functionality will not work with IE");
    //    $("#btnExportProperties").attr("data-toggle", "tooltip");
    //    $("#btnExportProperties").hide();
    //}
    //else {
    //    $("#btnExportResults").show();
    //    $("#btnExportProperties").show();
    //}
}

function AddRequestResultToCache(odataUrl, propertyData, resultData, resultColumns) {
    //var cacheResult = requestCache[odataUrl];

    //if (cacheResult !== undefined) {
    //    return;
    //}

    //WriteConsole("AddRequestResultToCache()");
    //WriteConsole(odataUrl);
    //WriteConsole(nextResultOdataUrl);

    //var cacheEntry = { propertyData: propertyData, resultData: resultData, resultColumns: resultColumns, nextResultOdataUrl: nextResultOdataUrl };

    //requestCache[odataUrl] = cacheEntry;
}

function GetRequestResultFromCache(odataUrl) {
    //var cacheResult = requestCache[odataUrl];

    //if (cacheResult === undefined) {
    //    return null;
    //}
    //else {
    //    WriteConsole("GetRequestResultFromCache()");
    //    WriteConsole(odataUrl);
    //    WriteConsole(cacheResult.nextResultOdataUrl);

    //    nextResultOdataUrl = cacheResult.cacheResult;
    //    return cacheResult;
    //}

    return null;
}

function SetTreeHeight() {

    var sidebarDivHeight = $('#SPEsidebar')[0].scrollHeight;
    //var searchTextBoxDivHeight = $("#searchTextBoxDiv")[0].scrollHeight;

    $("#spExplorerTreeScrollDiv").height(sidebarDivHeight);
}

function SetHeight() {
    
    $("#tabPropertiesScrollDiv").height(50);
    $("#tabResultsScrollDiv").height(50);
    $("#tabCamlQueryDiv").height(50);
    $("#tabCamlResultDiv").height(50);
    $("#tabCamlQuerySelectFieldsDiv").height(50);
    $("#tabCamlQuerySelectFieldsListDiv").height(50);
    $("#tabCamlQueryText").height(50);
    $("#tabCamlQueryOptions").height(50);
    
    $("#divTab").height(50);

    var mainDivHeight = $('#SPEmain')[0].scrollHeight;
    var mainFooter = $("#SPEfooter")[0].scrollHeight;
    var requestInfoHeight = $("#oDataRequestInfo")[0].scrollHeight;
    var tabResultsHeight = $("#tabResults")[0].scrollHeight;
    var tabPropertiesHeight = $("#tabProperties")[0].scrollHeight;
    var tabCamlGenerator = $("#tabCamlGenerator")[0].scrollHeight;

    var actualHeight = 0;
    var mainTabHeight = 0;

    if (tabPropertiesHeight === 0) {
        mainTabHeight = tabResultsHeight;
    }
    else {
        mainTabHeight = tabPropertiesHeight;
    }

    actualHeight = mainDivHeight - mainFooter - requestInfoHeight - mainTabHeight;

    actualHeight = actualHeight;

    $("#tabPropertiesScrollDiv").height(actualHeight + 8);

    //if (tabResultsHeight === 0) {
    //    actualHeight = mainDivHeight - mainFooter - requestInfoHeight - tabPropertiesHeight;
    //}
    //else {
    //    actualHeight = mainDivHeight - mainFooter - requestInfoHeight - tabResultsHeight;
    //}

    //actualHeight = actualHeight + 7;
    $("#tabResultsScrollDiv").height(actualHeight + 3);

    var camlTabHeight = mainDivHeight - mainFooter - requestInfoHeight - mainTabHeight + 3;
    $("#tabCamlQueryDiv").height(camlTabHeight);
    $("#tabCamlResultDiv").height(camlTabHeight);
    $("#tabCamlQuerySelectFieldsDiv").height(camlTabHeight - 5);
    
    //workaround to get height of hidden element [START]
    var tabCamlGeneratorClass = $("#tabCamlGenerator").attr('class');
    $("#tabCamlGenerator").attr('class', '');
    var tabtabCamlQueryClass = $("#tabCamlQuery").attr('class');
    $("#tabCamlQuery").attr('class','');
    var tabCamlQuerySelectFieldsHeader = $("#tabCamlQuerySelectFieldsHeader").height();
    $("#tabCamlGenerator").attr('class', tabCamlGeneratorClass);
    $("#tabCamlQuery").attr('class', tabtabCamlQueryClass);
    //workaround to get height of hidden element [END]

    $("#tabCamlQuerySelectFieldsListDiv").height(camlTabHeight - tabCamlQuerySelectFieldsHeader -5);
    $("#tabCamlQueryText").height(camlTabHeight);
    $("#tabCamlQueryOptions").height(camlTabHeight);
    $("#textareaCamlQuery").height(camlTabHeight - 90);
    //TODO: do not use 65px
    $("#tabCamlListFieldsDetailsDiv").height(camlTabHeight);

    var sidebarWidth = $("#spExplorerTreeScrollDiv").width();
    //$("#ddlUrl").width(sidebarWidth - 40);
    //$("#ddlSelectAccessPoint").width(sidebarWidth);
    //$("#btnGo").width(50);
}

function LoadJSTree(currentWebUrl) {
    var rootNodeGuid = CreateRootNode(currentWebUrl);
    //$('.tree li.parent_li > span').on('click', function (e) {
    $("body").on("click", ".tree li.parent_li > span", SPExplorerTree_Select);

    var selectedNodeObj = $("span[id='" + rootNodeGuid + "']");
    $(".selected_li").removeClass('selected_li');
    selectedNodeObj.addClass('selected_li');

    var objectNode = selectedNodeObj[0];

    ExpandNode($(objectNode));
}

function CreateRootNode(currentWebUrl) {
    

    var rootNodeGuid = guid();

    var rootNodeHtml = "<ul>" +
        "<li class=\"parent_li\">" +
            "<span ID=\"" + rootNodeGuid + "\" NodeType=\"SPWeb\" ODataUrl=\"" + currentWebUrl + "/" + $("#txtRestService").val() + "\" ><i class=\"icon-minus-sign\"></i> Root</span>" +
        "</li>" +
    "</ul>";

    $("#spExplorerTree").html(rootNodeHtml);

    return rootNodeGuid;
}

function SPExplorerTree_Init() {
    $("#tblProperties").find("tr:gt(0)").remove();
    $("#tabResultsScrollDiv").html('');
    $("#ulSelectColumns").html('');
}
function SPExplorerTree_Select(e) {
    try {
        pageNavigationIndexArray = [];

        var selectedNodeObj = $(this);

        currentPageIndex = 1;

        pageNavigationIndexArray[currentPageIndex] = selectedNodeObj.attr("ODataUrl");

        var children = selectedNodeObj.parent('li.parent_li').find(' > ul > li');
        var objectNode = selectedNodeObj[0];

        var isSelected = selectedNodeObj.hasClass('selected_li');

        if (isSelected === false) {
            ShowProgress();
            SPExplorerTree_Init();
            selectedNodeObj.find(' > i').addClass('icon-minus-sign').removeClass('icon-plus-sign');
            ExpandNode($(objectNode));
            $(".selected_li").removeClass('selected_li');
            selectedNodeObj.addClass('selected_li');
        }
        else {
            if (children.length > 0) {
                if (children.is(":visible")) {
                    children.hide('fast');
                    selectedNodeObj.find(' > i').addClass('icon-plus-sign').removeClass('icon-minus-sign');
                } else {
                    children.show('fast');
                    selectedNodeObj.find(' > i').addClass('icon-minus-sign').removeClass('icon-plus-sign');
                }
            }
        }

        //if (children.length <= 0 && isSelected === false) {
        //    selectedNodeObj.find(' > i').addClass('icon-minus-sign').removeClass('icon-plus-sign');

        //    //var childNodesText = "<ul>" +
        //    //                        "<li class=\"parent_li\">" +
        //    //                            "<span><i class=\"icon-plus-sign\"></i> Child</span>" +
        //    //                        "</li>" +
        //    //                    "</ul>";


        //    //$(objectNode).after(childNodesText);
        //    ExpandNode($(objectNode));
        //}
        //else {
        //    if (isSelected === false) {
        //        //setTimeout(
        //        //  function () {
        //        //WriteConsole("expanding from cache...");
        //        ExpandNodeFromCache($(objectNode));
        //        //}, 10000);
        //    }

        //    if (children.is(":visible")) {
        //        children.hide('fast');
        //        selectedNodeObj.find(' > i').addClass('icon-plus-sign').removeClass('icon-minus-sign');
        //    } else {
        //        children.show('fast');
        //        selectedNodeObj.find(' > i').addClass('icon-minus-sign').removeClass('icon-plus-sign');
        //    }

        //    HideProgress();
        //}



        e.stopPropagation();
    }
    catch (err) {
        ShowError(err);
    }
}

function AddChildRootNodes(selectedNodeObj, data, spNodeType) {

    var childNodeHtml = "<ul>";

    for (var propertyKey in data.d) {

        if (propertyKey === null) {
            continue;
        }

        objWebProperty = data.d[propertyKey];

        if (objWebProperty === null || objWebProperty["__deferred"] === undefined || objWebProperty["__deferred"]["uri"] === undefined) {
            continue;
        }

        var odataUrl = objWebProperty["__deferred"]["uri"]

        childNodeHtml = childNodeHtml + "<li class=\"parent_li\">" +
                                                "<span ID=\"" + guid() + "\" NodeType=\"" + spNodeType + "." + propertyKey + "\" ODataUrl=\"" + odataUrl + "\"><i class=\"icon-plus-sign\"></i> " + propertyKey + "</span>" +
                                            "</li>";
    }

    childNodeHtml = childNodeHtml + "</ul>";

    selectedNodeObj.after(childNodeHtml);
}

function AddChildPropertyNodes(selectedNodeObj, data, spNodeType) {

    if (data.d["__next"]) {
        nextResultOdataUrl = data.d["__next"];
    }
    else {
        nextResultOdataUrl = "";
    }

    var propertyRowsHtml = "";

    for (var propertyName in data.d) {
        propertyValue = data.d[propertyName];

        if (typeof (propertyValue) !== "object") {
            //AddPropertyRow(propertyName, propertyValue);

            htmlEncodePropertyValue  = htmlEncode(propertyValue);
            
            if (jQuery.inArray(spNodeType, listNodeTypeValues) !== -1) {
                if (propertyName === "Title") {
                    $("#spListTitle").text(propertyValue);
                }
                else if (propertyName === "Id") {
                    $("#spListId").text(propertyValue);
                }
            }
            propertyRowsHtml = propertyRowsHtml + '<tr><td>' + propertyName + '</td><td>' + htmlEncodePropertyValue + '</td></tr>';
        }
    }

    BindPropertiesTable(propertyRowsHtml)

    return propertyRowsHtml;
}

function BindPropertiesTable(propertyRowsHtml) {
    $("#tblProperties").find("tr:gt(0)").remove();
    $("#tblProperties").show();
    $('#tblProperties tr:last').after(propertyRowsHtml);
}

function AddPropertyRow(propertyName, propertyValue) {
    $('#tblProperties tr:last').after('<tr><td>' + propertyName + '</td><td>' + propertyValue + '</td></tr>');
}

function GetNodeText(objSPNode) {

    var nodeText = null;
    var nodeProperties = ["Title", "Name", "Id", "PrincipalId", "DefinitionId", "ReceiverId"];

    for (counter = 0; counter < nodeProperties.length; counter++) {
        nodeText = objSPNode[nodeProperties[counter]];
        if (nodeText !== undefined && nodeText !== null) {
            nodeText = htmlEncode(nodeText);
            break;
        }
    }

    return nodeText;
}

function AddChildResultNodes(selectedNodeObj, data, spNodeType, propertyRowsHtml, oDataUrl) {
    
    var childNodeHtml = "<ul>";

    var resultColumns = [];

    var jsonObject = "[";

    if (data.d.results !== undefined) {
        for (resultIndex = 0; resultIndex < data.d.results.length; resultIndex++) {
            //for (var resultIndex in data.d.results) {

            objSPNode = data.d.results[resultIndex];

            //if (resultsHTML === "") {
            //    resultsHTML = "<table id=\"tblResults\" class='table table-hover' style=\"display:none\">";
            //    resultsHTML = GetResultColumn(objSPNode);
            //}

            var childSPNodeType = spNodeType;
            if (objSPNode !== undefined &&
                    objSPNode.__metadata !== undefined &&
                    objSPNode.__metadata.type !== undefined) {
                childSPNodeType = spNodeType + "." + objSPNode.__metadata.type;
            }

            var nodeText = GetNodeText(objSPNode);

            childNodeHtml = childNodeHtml + "<li class=\"parent_li\">" +
                                               "<span ID=\"" + guid() + "\" NodeType=\"" + childSPNodeType + "\" ODataUrl=\"" + objSPNode.__metadata.uri + "\"><i class=\"icon-plus-sign\"></i> " + nodeText + "</span>" +
                                           "</li>";

            //resultsHTML = resultsHTML + AddResultRow(objSPNode);

            var jsonRowValue = GetJsonRow(objSPNode, false);

            if (jsonRowValue.length !== "") {
                if (jsonObject.length > 1) {
                    jsonObject = jsonObject + ",";
                }

                jsonObject = jsonObject + jsonRowValue;
            }

            for (propertyKey in objSPNode) {
                if (typeof (objSPNode[propertyKey]) !== "object") {

                    if (jQuery.inArray(propertyKey, resultColumns) === -1) {
                        resultColumns.push(propertyKey);
                    }
                }
            }
        }
    }
    childNodeHtml = childNodeHtml + "</ul>"

    if (spNodeType !== "SPWeb.AppTiles") {
        selectedNodeObj.after(childNodeHtml);
    }

    //resultsHTML = resultsHTML + "</table>";

    jsonObject = jsonObject + "]";

    var jsonGridData = JSON.parse(jsonObject);

    BindResultGrid(jsonGridData, resultColumns);

    //$("#tblResults").html(resultsHTML);

    AddRequestResultToCache(oDataUrl, propertyRowsHtml, jsonGridData, resultColumns);
}

function GetJsonRow(objSPNode, includeNull) {
    var jsonRow = "{";

    for (propertyKey in objSPNode) {
        var jsonPropertyKeyValue = "";
        var jsonPropertyValue = objSPNode[propertyKey];
        //var objValue = objSPNode[propertyKey];

        if (includeNull === true && objSPNode[propertyKey] === null) {
            jsonPropertyValue = "";
        }

        if (typeof (jsonPropertyValue) !== "object") {
            //var jsonPropertyValue = htmlEncode(objSPNode[propertyKey]);
            //var jsonPropertyValue = objSPNode[propertyKey];
            //jsonPropertyValue = jsonPropertyValue.replace('"', '\"');
            //jsonPropertyValue = jsonPropertyValue.replace("\\", "\\\\");

            if (jQuery.type(jsonPropertyValue) === "string") {
                jsonPropertyValue = htmlEncode(jsonPropertyValue);
                jsonPropertyValue = jsonPropertyValue.replace(/(\r\n|\n|\r)/gm, "");
                jsonPropertyValue = jsonPropertyValue.replace(/\\/g, "\\\\")
                jsonPropertyValue = jsonPropertyValue.replace(/\"/g, "\\\"");
                
            }

            //jsonPropertyValue = jsonPropertyValue.replace("/", "\\/");

            if (jsonPropertyValue === undefined) {
                jsonPropertyValue = "";
            }
            
            jsonPropertyKeyValue = "\"" + propertyKey + "\" : " + "\"" + jsonPropertyValue + "\"";
        }

        if (jsonPropertyKeyValue.length > 0) {
            if (jsonRow.length > 1) {
                jsonRow = jsonRow + ",";
            }

            jsonRow = jsonRow + jsonPropertyKeyValue;
        }
    }

    jsonRow = jsonRow + "}";

    if (jsonRow.length === 2) {
        jsonRow = "";
    }
    
    var tempJsonData = JSON.parse("[" + jsonRow + "]");
    
    return jsonRow;
}

function EncodeJasonValue(jsonPropertyValue) {
    jsonPropertyValue = htmlEncode(jsonPropertyValue);
    jsonPropertyValue = jsonPropertyValue.replace(/(\r\n|\n|\r)/gm, "");
    jsonPropertyValue = jsonPropertyValue.replace(/\\/g, "\\\\")
    jsonPropertyValue = jsonPropertyValue.replace(/\"/g, "\\\"");
    return jsonPropertyValue;
}

function BindResultGrid(jsonGridData, resultColumns) {
    var spNodeType = $("#spNodeType").text();

    if (nextResultOdataUrl !== "") {
        $("#nextResultSet").show();
        $("#nextResultSet").prop("disabled", false);
        $("#nextResultSet").attr("nextResultOdataUrl", nextResultOdataUrl);
    }
    else {
        if (jQuery.inArray(spNodeType, itemNodeTypeValues) !== -1) {
            $("#nextResultSet").show();
            $("#nextResultSet").prop("disabled", true);
        }
        else {
            $("#nextResultSet").hide();
        }
    }

    if (currentPageIndex > 1) {
        $("#previousResultSet").show();
        $("#previousResultSet").prop("disabled", false);
    }
    else {
        if (jQuery.inArray(spNodeType, itemNodeTypeValues) !== -1) {
            $("#previousResultSet").show();
            $("#previousResultSet").prop("disabled", true);
        }
        else {
            $("#previousResultSet").hide();
        }
    }

    var selectColumnsHtml = "";
    var strColumns = "";
    $.each(resultColumns, function (index, value) {
        if (strColumns.length > 0) {
            strColumns = strColumns + ", ";
        }
        strColumns = strColumns + "{ \"name\" : \"" + value + "\", \"type\": \"text\" }";
        selectColumnsHtml = selectColumnsHtml + "<li><input type=\"checkbox\" checked=\"checked\" onclick=\"ShowHideColumns(event, this, '" + (index + 1) + "')\">" + value + "</input></li>";
    });

    //<input type="checkbox" name="col1" checked="checked" /> Hide/Show Column 1 <br />
    $("#ulSelectColumns")[0].innerHTML = selectColumnsHtml;

    strColumns = "[ " + strColumns + " ]";


    var jsonColuns = JSON.parse(strColumns);

    var resultsHTML = "Result count: " + jsonGridData.length;

    resultsHTML = resultsHTML + "<table id=\"bootGridResults\" class=\"table table-condensed table-hover table-striped\">";

    resultsHTML = resultsHTML + "<thead><tr>";
    for (jsonColunIndex = 0; jsonColunIndex < jsonColuns.length; jsonColunIndex++) {

        var jsonColumnName = jsonColuns[jsonColunIndex].name;

        //if (jsonColumnName !== "SchemaXml") {
        //    continue;
        //}

        resultsHTML = resultsHTML + "<th data-column-id=\"" + jsonColumnName + "\">" + jsonColumnName + "</th>";
    }
    resultsHTML = resultsHTML + "</tr></thead><tbody>";


    for (jsonRowIndex = 0; jsonRowIndex < jsonGridData.length; jsonRowIndex++) {
        resultsHTML = resultsHTML + "<tr>";

        var jsonRow = jsonGridData[jsonRowIndex];
        for (jsonColunIndex = 0; jsonColunIndex < jsonColuns.length; jsonColunIndex++) {
            var jsonColumnName = jsonColuns[jsonColunIndex].name;
            var columnValue = jsonRow[jsonColumnName]

            if (columnValue === undefined) {
                columnValue = "";
            }

            //if (jsonColumnName !== "SchemaXml") {
            //    continue;
            //}

            //if (jsonColumnName === "SchemaXml") {
            //    resultsHTML = resultsHTML + "<td><![CDATA[" + columnValue + "]]></td>";
            //}
            //else {
            //if(columnValue){
            //    columnValue = columnValue.replace(/\"/g, "\\\"");
            //}
            resultsHTML = resultsHTML + "<td>" + columnValue + "</td>";
            //}
        }

        resultsHTML = resultsHTML + "</tr>";
    }
    resultsHTML = resultsHTML + "</tbody></table>";
    $("#tabResultsScrollDiv").html(resultsHTML);


    //$("#bootGridResults").bootgrid();
}

function AddChildNodes(selectedNodeObj, data, spNodeType, oDataUrl) {
    try {
        AddChildRootNodes(selectedNodeObj, data, spNodeType);
        var propertyRowsHtml = AddChildPropertyNodes(selectedNodeObj, data, spNodeType);
        AddChildResultNodes(selectedNodeObj, data, spNodeType, propertyRowsHtml, oDataUrl);
    }
    catch (err) {
        ShowError(err);
    }
}

function ExpandNode(selectedNodeObj) {
    hideTab("tabCamlGenerator");
    var spNodeType = selectedNodeObj.attr("NodeType");
    
    var oDataUrl = selectedNodeObj.attr("ODataUrl");

    var childNodes = selectedNodeObj.parent().find("ul");
    childNodes.remove();

    UpdateProgressText("Requesting " + oDataUrl);

    ExpandNodeFromOdata(selectedNodeObj, spNodeType, oDataUrl);
}

function ExpandNodeFromOdata(selectedNodeObj, spNodeType, oDataUrl) {

    currentResultOdataUrl = oDataUrl;

    if (isHostDataRequest) {
        oDataUrl = GetUrlWithAppContext(oDataUrl);
    }
    
    var requestInfo = "<div><input type='text' value=\"ODataUrl: " + oDataUrl + "\" readonly='readonly' /></div>";
    requestInfo = requestInfo + "<div>NodeType: " + spNodeType + "</div>";

    $("#spNodeType").text(spNodeType);
    $("#spOdataUrl").text(oDataUrl);

    var selectedTabId = $("ul#tabsResults li.active a").attr("href");
    if (!(selectedTabId === "#tabProperties" || selectedTabId === "#tabResults"))
    {
        showTab("tabProperties");
    }

    if (jQuery.inArray(spNodeType, listNodeTypeValues) !== -1) {
        $("#spListOdataUrl").text(oDataUrl);
    }
    
    if (jQuery.inArray(spNodeType, itemNodeTypeValues) !== -1) {
        $("#btnShowCamlBuilder").show();
    }
    else {
        $("#btnShowCamlBuilder").hide();
    }

    $("#oDataRequestInfo").show();
    $("#oDataRequestInfo").html(requestInfo);

    if (spNodeType === "SPList.Items") {
        oDataUrl = oDataUrl + "?select=Title"
    }

    $.ajax({
        url: oDataUrl,
        type: "GET",
        headers: { "ACCEPT": "application/json;odata=verbose" },
        success: function (data, object) {

            AddChildNodes(selectedNodeObj, data, spNodeType, oDataUrl);
            HideProgress();
        },
        error: errorHandler
    });
}

function ExpandNodeFromCache(selectedNodeObj) {
    var oDataUrl = selectedNodeObj.attr("ODataUrl");

    var requestResult = GetRequestResultFromCache(oDataUrl);

    var propertyData = requestResult.propertyData;
    BindPropertiesTable(propertyData);

    var resultColumns = requestResult.resultColumns;
    var resultData = requestResult.resultData;

    BindResultGrid(resultData, resultColumns);
}

function errorHandler(XMLHttpRequest, textStatus, errorThrown) {
    WriteConsole("Error : " + textStatus + ": " + XMLHttpRequest.responseText);

    var modelTitle = "Error";
    var modelBody = "<h4>" + textStatus + " - " +errorThrown + "</h4>";

    try {
        var errorObj = JSON.parse(XMLHttpRequest.responseText);
        modelBody = modelBody + "<h6>Error Code: " + escapeXml(errorObj.error.code) + "</h6>";
        modelBody = modelBody + "<h6>Error Message: " + escapeXml(errorObj.error.message.value) + "</h6>";
    } catch (e) {
        modelBody = modelBody + "<h6>" +escapeXml(XMLHttpRequest.responseText) + "</h6>";
    }
    ShowModelDialogBox(modelTitle, modelBody);
}

function escapeXml(xmlData) {

    var newXmlData = xmlData.replace(/\"/g, "&quot;");
    newXmlData = newXmlData.replace(/'/g, "&apos;");
    newXmlData = newXmlData.replace(/</g, "&lt;");
    newXmlData = newXmlData.replace(/>/g, "&gt;");

    return newXmlData;
}

function ShowError(objError) {
    var modelTitle = "Error";
    var modelBody = "<h4>" + objError.number + " : " + objError.message + "</h4>";
    modelBody = modelBody + "<h5>" + objError.description + "</h5>";
    modelBody = modelBody + "<h6>" + objError.stack + "</h6>";

    ShowModelDialogBox(modelTitle, modelBody);
}

function ShowModelDialogBox(modelTitle, modelBody) {

    HideProgress();

    $("#SPEModalDialogBoxLabel").html(modelTitle);
    $("#SPEModalDialogBoxBody").html(modelBody);

    $('#SPEModalDialogBox').modal();
}

function ShowProgress() {
    $('#processing-modal').modal('show');
}

function HideProgress() {
    $('#processing-modal').modal('hide');
}

function UpdateProgressText(progressText) {
    $("#lblProgressBarText").text(progressText);
    //setTimeout(
    //  function () {
    //      //do something special
    //  }, 100);
}

function WriteConsole(consoleMsg) {
    if (window.console) {
        console.log(consoleMsg);
    }
}

function htmlEncode(value) {
    //create a in-memory div, set it's inner text(which jQuery automatically encodes)
    //then grab the encoded contents back out.  The div never exists on the page.
    return $('<div/>').text(value).html();
}

function htmlDecode(value) {
    return $('<div/>').html(value).text();
}

function ExportHTMLTable(htmlTableId) {
    //var htmlTableContent = $('#' + htmlTableId).html();
    //window.open('data:application/vnd.ms-excel,' + encodeURIComponent(htmlTableContent));

    ////function TableToExcel(tableid) {
    //var id = $('[id$="' + htmlTableId + '"]');
    //var strCopy = $('<div></div>').html(id.clone()).html();
    //window.clipboardData.setData("Text", strCopy);
    //var objExcel = new ActiveXObject("Excel.Application");
    //objExcel.visible = false; var objWorkbook = objExcel.Workbooks.Add; var objWorksheet = objWorkbook.Worksheets(1); objWorksheet.Paste; objExcel.visible = true;
    ////}

    fnExcelReport(htmlTableId);
}

function fnExcelReport(htmlTableId) {
    var tab_text = "<table border='2px'><tr bgcolor='#87AFC6'>";
    var textRange; var j = 0;
    tab = document.getElementById(htmlTableId); // id of table

    for (j = 0 ; j < tab.rows.length ; j++) {
        tab_text = tab_text + tab.rows[j].innerHTML + "</tr>";
        //tab_text=tab_text+"</tr>";
    }

    tab_text = tab_text + "</table>";
    tab_text = tab_text.replace(/<A[^>]*>|<\/A>/g, "");//remove if u want links in your table
    tab_text = tab_text.replace(/<img[^>]*>/gi, ""); // remove if u want images in your table
    tab_text = tab_text.replace(/<input[^>]*>|<\/input>/gi, ""); // reomves input params

    var ua = window.navigator.userAgent;
    var msie = ua.indexOf("MSIE ");

    if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))      // If Internet Explorer
    {
        frameExportToExcel.document.open("txt/html", "replace");
        frameExportToExcel.document.write(tab_text);
        frameExportToExcel.document.close();
        frameExportToExcel.focus();
        sa = frameExportToExcel.document.execCommand("SaveAs", true, "ExportToExcel.xls");
    }
    else                 //other browser not tested on IE 11
        sa = window.open('data:application/vnd.ms-excel,' + encodeURIComponent(tab_text));

    return (sa);
}

function ShowHideColumns(event, objCheckBox, columnIndex) {
    if (objCheckBox.checked === false) {
        $('#bootGridResults td:nth-child(' + columnIndex + '),#bootGridResults th:nth-child(' + columnIndex + ')').hide();
    }
    else {
        $('#bootGridResults td:nth-child(' + columnIndex + '),#bootGridResults th:nth-child(' + columnIndex + ')').show();
    }

    event.stopPropagation()
}

function guid() {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
          .toString(16)
          .substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
      s4() + '-' + s4() + s4() + s4();
}

function NextResultSet() {
    ShowProgress();
    previousResultOdataUrl = currentResultOdataUrl;
    var nextResultOdataUrl = $("#nextResultSet").attr("nextResultOdataUrl");

    var selectedNodeObj = GetSelectedNode();

    var spNodeType = selectedNodeObj.attr("NodeType");
    var oDataUrl = selectedNodeObj.attr("ODataUrl");

    currentPageIndex = currentPageIndex + 1;

    pageNavigationIndexArray[currentPageIndex] = nextResultOdataUrl;

    ExpandNodeFromOdata(selectedNodeObj, spNodeType, nextResultOdataUrl);
}

function PreviousResultSet() {
    ShowProgress();
    if (currentPageIndex > 1) {

        var nextResultOdataUrl = pageNavigationIndexArray[currentPageIndex];
        $("#nextResultSet").attr("nextResultOdataUrl", nextResultOdataUrl)
        $("#nextResultSet").show();

        currentPageIndex = currentPageIndex - 1;

        var selectedNodeObj = GetSelectedNode();
        var spNodeType = selectedNodeObj.attr("NodeType");

        var oDataUrl = pageNavigationIndexArray[currentPageIndex];

        ExpandNodeFromOdata(selectedNodeObj, spNodeType, oDataUrl);
    }
}

function GetSelectedNode() {

    return $(".selected_li");
}

function ddlSelectAccessPoint_onchange(ddlSelectAccessPoint) {
    var selectedAccessPoint = $(ddlSelectAccessPoint).val();
    $("#txtRestService").val(selectedAccessPoint);

    var currentWebUrl = $("#txtRootWebUrl").val();
    LoadJSTree(currentWebUrl);
}